package com.easy.util;

import com.easy.mapper.ScheduleMapper;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 多班次剩余票数管理器
 * 基于内存存储，使用原子类保证并发安全
 */
@Component
public class TicketInventoryManager {
    // 存储所有班次的剩余票数: key=scheduleId, value=原子计数器
    private final Map<Integer, AtomicInteger> ticketInventory = new ConcurrentHashMap<>();

    // 数据库操作接口
    @Autowired
    private  ScheduleMapper scheduleMapper;


    @PostConstruct
    private void init() {
        // 初始化时加载所有班次的剩余票数到内存
        initAllScheduleTickets();
    }
    public TicketInventoryManager() {
    }

    private void initAllScheduleTickets() {
        try {
            // 从数据库查询所有有效的班次及其剩余票数
            Map<Integer, Map<String, Object>> dbTickets = (Map<Integer, Map<String, Object>>) (Map<?, ?>) scheduleMapper.selectAllRemainingSeats();
            System.out.println("从数据库加载所有班次的剩余票数：" + dbTickets);

            if (dbTickets == null) {
                System.err.println("警告: 查询返回null，没有加载任何班次数据");
                return;
            }

            System.out.println("查询到 " + dbTickets.size() + " 条班次数据");

            // 初始化原子计数器
            for (Map.Entry<Integer, Map<String, Object>> entry : dbTickets.entrySet()) {
                if (entry == null || entry.getKey() == null || entry.getValue() == null) {
                    continue;
                }

                Integer scheduleId = entry.getKey();
                Map<String, Object> valueMap = entry.getValue();

                // 从Map中提取remain_seats值
                Object remainSeatsObj = valueMap.get("remain_seats");
                if (remainSeatsObj == null) {
                    remainSeatsObj = valueMap.get("remainSeats");
                }

                int remainingSeats = 0;
                if (remainSeatsObj instanceof Number) {
                    remainingSeats = ((Number) remainSeatsObj).intValue();
                } else if (remainSeatsObj != null) {
                    try {
                        remainingSeats = Integer.parseInt(remainSeatsObj.toString());
                    } catch (NumberFormatException e) {
                        System.err.println("无法解析剩余票数: " + remainSeatsObj);
                    }
                }

                ticketInventory.put(scheduleId, new AtomicInteger(remainingSeats));
                System.out.println("初始化班次 " + scheduleId + " 剩余票数: " + remainingSeats);
            }

            System.out.println("成功初始化 " + ticketInventory.size() + " 个班次的票务库存");
        } catch (Exception e) {
            System.err.println("初始化票务库存时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 为指定班次扣减票数
     * @param scheduleId 班次ID
     * @param num 扣减数量
     * @return 扣减是否成功
     */
    public boolean deductTickets(int scheduleId, int num) {
        if (num <= 0) {
            throw new IllegalArgumentException("扣减数量必须大于0");
        }

        // 获取该班次的原子计数器，若不存在则初始化(防止未加载的新增班次)
        AtomicInteger counter = ticketInventory.computeIfAbsent(
                scheduleId,
                k -> new AtomicInteger(scheduleMapper.selectRemainingSeats(k))
        );

        // 循环尝试扣减，直到成功或确定失败
        while (true) {
            int current = counter.get();
            // 检查剩余票数是否充足
            if (current < num) {
                return false; // 票数不足，扣减失败
            }
            // 原子操作：当前值等于预期值时才扣减
            if (counter.compareAndSet(current, current - num)) {
                // 同步更新到数据库(实际项目中建议异步批量更新优化性能)
                boolean dbSuccess = scheduleMapper.updateRemainingSeats(scheduleId, current - num)>0;
                if (!dbSuccess) {
                    // 数据库更新失败时回滚内存计数(简单处理，实际需更复杂的补偿机制)
                    counter.addAndGet(num);
                    return false;
                }
                return true; // 扣减成功
            }
            // CAS失败则重试(可能被其他线程修改)
        }
    }




    /**
     * 获取指定班次的剩余票数
     */
    public int getRemainingTickets(int scheduleId) {
        AtomicInteger counter = ticketInventory.get(scheduleId);
        return counter != null ? counter.get() : 0;
    }

//    /**
//     * 手动刷新指定班次的票数(从数据库重新加载)
//     * 用于处理内存与数据库不一致的情况
//     */
//    public void refreshTicketCount(int scheduleId) {
//        int dbCount = scheduleMapper.selectRemainingSeats(scheduleId);
//        ticketInventory.put(scheduleId, new AtomicInteger(dbCount));
//    }

    /**
     * 恢复指定班次剩余票数
     */
    public boolean addTickets(int scheduleId, int num) {
        if (num <= 0) {
            throw new IllegalArgumentException("增加数量必须大于0");
        }

        // 获取该班次的原子计数器，若不存在则初始化(防止未加载的新增班次)
        AtomicInteger counter = ticketInventory.computeIfAbsent(
                scheduleId,
                k -> new AtomicInteger(scheduleMapper.selectRemainingSeats(k))
        );

        // 循环尝试增加，直到成功
        while (true) {
            int current = counter.get();
            // 检查增加后的票数是否合理
            int newCount = current + num;
            // 检查整数溢出
            if (newCount < current) {
                return false; // 发生溢出
            }

            // 原子操作：当前值等于预期值时才增加
            if (counter.compareAndSet(current, newCount)) {
                // 同步更新到数据库(实际项目中建议异步批量更新优化性能)
                boolean dbSuccess = scheduleMapper.updateRemainingSeats(scheduleId, newCount) > 0;
                if (!dbSuccess) {
                    // 数据库更新失败时回滚内存计数(简单处理，实际需更复杂的补偿机制)
                    counter.addAndGet(-num);
                    return false;
                }
                return true; // 增加成功
            }
            // CAS失败则重试(可能被其他线程修改)
        }
    }


}
